#include <iostream>
#include <vector>
#include <memory>

using namespace std;


//1.定性： 什么情况下需要管理？----堆区内存开辟的状况下
//2.指针定性：我们理解指针的应用，一般类的使用，但凡当前对象需要出去给第三方使用，采用指针
//3.需要自动管理，利用智能指针完成

class Widget{
    int m_x;
    int m_y;
    int m_z;

public:
    Widget(int x,int y , int z):
            m_x(x), m_y(y),m_z(z)
    {}

    void print(){
        cout<<m_x<<","<<m_y<<","<<m_z<<endl;
    }

    ~Widget()
    {
        cout<<"Widget dtor"<<endl;
    }
};
int widget_display()
{
    Widget* w0 = new Widget(1, 2, 3);
    unique_ptr<Widget> w1(new Widget(1, 2, 3));

    std::cout <<"pointer size:" << sizeof(w0) << endl;
    std::cout <<"unique_ptr size:"<< sizeof(w1) << endl;
}

struct DeleteWithLog {
    void operator()(Widget* w) {
        data++;
        delete w;
        cout << "------ DeleteWithLog delete w" << endl;
    }

    int data; //一般不建议在函数对象中定义实例成员
};

void deleteFunction(Widget* w) {
    delete w;
    cout << "------ deleteFunction delete w" << endl;
}


int main()
{
    widget_display();

    //初始化方式1
//    std::unique_ptr<int> up1(new int(123));
//    //初始化方式2
//    std::unique_ptr<int> up2;
//    up2.reset(new int(123));

//    std::auto_ptr<string> p1(new string("data1"));
//    std::auto_ptr<string> p2;
//    //
//    p2 = p1;    //编译器认为合法，但后续对p1继续使用，程序运行时出错，因为p1不再指向有效数据。
//
//    cout<<  p1.get()<<endl;


    //保证唯一
//    std::unique_ptr<string> p3(new string("data2"));
//    std::unique_ptr<string> p4;
//    p4 = p3;    // 编译器认为非法，避免p3不再指向有效数据问题。




    //初始化方式3 (-std=c++14) 更安全
    //要说得更合理std::unique_ptr，std::shared_ptr这是专门由智能指针提供的一种封装
    //其目的是要我们不再去自己使用new运算符， 因为可能会出现安全隐患
    //td::make_unique<int>  官方推荐方案 new int  有什么区别？
    //无区别：原因，因为官方标准，提出，不想要在你的代码看到有任何new
    //设计理念的不一样，JAVA的标准，和C++的标准区别大
    //JAVA更符合逻辑
    //C++更尊崇与内存角度去看问题！
    std::unique_ptr<int> up3 = std::make_unique<int>(123);

    //语法，设计角度
    //JAVA成熟语言熏陶过的！
    //








    //unique_ptr主要核心目的是为了确保数据的唯一性
    //nullptr 是否是空指针
    //move主要的目的是要保证数据只有一份，清空原来的，将数据保存到下一个！
//    std::unique_ptr<int> up1(std::make_unique<int>(123));
//    std::unique_ptr<int> up2(std::move(up1));  //通过移动实现了复制操作
//    std::cout << ((up1.get() == nullptr) ? "up1 is NULL" : "up1 is not NULL") << std::endl;

//    std::unique_ptr<int> up3;
//    up3 = std::move(up2);    //通过移动实现了复制操作
//    std::cout << ((up2.get() == nullptr) ? "up2 is NULL" : "up2 is not NULL") << std::endl;


}

